import wx
import ConfigParser

import util
import itunes 

ID_NEXT_TRACK = 10
ID_PREV_TRACK = 20
ID_PLAY_PAUSE = 30
ID_STOP = 40
ID_SHOW_INFO = 50
ID_SHUFFLE = 60

#additional defines
GWL_EXSTYLE      = -20
WS_EX_NOACTIVATE = 0x08000000

autoshow_enabled = True

class InfoPopup(wx.PopupWindow):
    def __init__(self, parent):
        pre = wx.PrePopupWindow()
        pre.Create(parent, wx.FRAME_TOOL_WINDOW | wx.NO_BORDER)
        # remember handle
        self.hwnd = pre.GetHandle ()
        import win32gui
        import winxpgui
        
        wsex = win32gui.GetWindowLong(self.hwnd, GWL_EXSTYLE)
        win32gui.SetWindowLong(self.hwnd, GWL_EXSTYLE, wsex | WS_EX_NOACTIVATE)
        self.PostCreate(pre)

        #wx.PopupWindow.__init__(self, parent, style)
        self.SetBackgroundColour("#333333")
       
        self.panel = wx.Panel(self, -1)

        #SONG NAME
        self.name = self.label(self.panel, "Name", "#ffffff", None)
        self.artist = self.label(self.panel, "Artist", "#CCCCCC", self.name)
        self.album = self.label(self.panel, "Album", "#CCCCCC", self.artist)
        
        itl = wx.Font(wx.DEFAULT, wx.DEFAULT, wx.ITALIC, wx.NORMAL)
        self.album.SetFont(itl)

        self.panel.Bind(wx.EVT_RIGHT_DOWN, self.on_click)
        self.Bind(wx.EVT_RIGHT_DOWN, self.on_click)
        wx.CallAfter(self.Refresh)
              
        TIMER_ID = 990
        self.timer = wx.Timer(self, TIMER_ID)
        wx.EVT_TIMER(self, TIMER_ID, self.on_timer)
        
    def label(self, parent, text, color, last):
        y = 2
        if last is not None:
            lp = last.GetPosition()
            ls = last.GetSize()
            y = lp.y + ls.height
        text = wx.StaticText(parent, -1, text, pos=(4, y))
        text.SetForegroundColour(color)
        text.Bind(wx.EVT_RIGHT_DOWN, self.on_click)
        text.SetSize(text.GetBestSize())
        return text
    
    def resize(self):
        height = self.name.GetSize().height + \
                    self.artist.GetSize().height + \
                    self.album.GetSize().height
        width = max(self.name.GetSize().width,
                         self.artist.GetSize().width,
                         self.album.GetSize().width)
        self.panel.SetSize((max(100, width + 20), height + 6))
        self.SetSize(self.panel.GetSize())
        
        screen = wx.ClientDisplayRect()
        x = screen[2] - self.GetSize().width - 3
        y = screen[3] - self.GetSize().height - 3
        self.SetPosition((x, y))

    def on_timer(self, event):
        self.timer.Stop()
        self.Show(False)
        
    def show(self, track):
        if track is None:
            return
        self.name.SetLabel(track.name.replace('&', '&&'))
        self.name.SetSize(self.name.GetBestSize())
        self.artist.SetLabel(track.artist.replace('&', '&&'))
        self.artist.SetSize(self.artist.GetBestSize())
        self.album.SetLabel(track.album.replace('&', '&&') if len(track.album) != 0 else "Unknown Album")
        self.album.SetSize(self.album.GetBestSize())
        self.resize()
        self.timer.Start(2500)
        self.Show(True)

    def on_click(self, evt):
        self.Show(False)

class TrayIcon(wx.TaskBarIcon):
    def __init__(self, icon, tooltip, frame):
        wx.TaskBarIcon.__init__(self)
        self.SetIcon(icon, tooltip)
        self.frame = frame
        
        self.MENU_INFO = 100
        self.MENU_PLAY_PAUSE = ID_PLAY_PAUSE
        self.MENU_NEXT = ID_NEXT_TRACK
        self.MENU_PREV = ID_PREV_TRACK
        self.MENU_STOP = ID_STOP
        self.MENU_EXIT = 600
        self.MENU_TOGGLE_POPUP = 700
        
        self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.on_info)
        self.Bind(wx.EVT_MENU, self.toggle_popup, id=self.MENU_TOGGLE_POPUP)
        self.Bind(wx.EVT_MENU, self.on_info, id=self.MENU_INFO)
        self.Bind(wx.EVT_MENU, self.on_action, id=self.MENU_PLAY_PAUSE)
        self.Bind(wx.EVT_MENU, self.on_action, id=self.MENU_NEXT)
        self.Bind(wx.EVT_MENU, self.on_action, id=self.MENU_PREV)
        self.Bind(wx.EVT_MENU, self.on_action, id=self.MENU_STOP)
        self.Bind(wx.EVT_MENU, self.on_close, id=self.MENU_EXIT)
    
    def toggle_popup(self, evt):
        global autoshow_enabled
        autoshow_enabled = not autoshow_enabled
    
    def on_info(self, evt):
        self.frame.show_info(forced=True)

    def on_action(self, evt):
        self.frame.on_hotkey(evt)            

    def on_close(self, evt):
        self.frame.cleanup()
    
    def CreatePopupMenu(self):
        global autoshow_enabled
        menu = wx.Menu()
        menu.Append(self.MENU_INFO, "Show Info")
        menu.AppendCheckItem(self.MENU_TOGGLE_POPUP, "Always Show Info")
        menu.AppendSeparator()
        menu.Append(self.MENU_PLAY_PAUSE, "Play/Pause")
        menu.Append(self.MENU_NEXT, "Next Track")
        menu.Append(self.MENU_PREV, "Previous Track")
        menu.Append(self.MENU_STOP, "Stop")
        menu.AppendSeparator()
        menu.Append(self.MENU_EXIT, "Exit")
        menu.Check(self.MENU_TOGGLE_POPUP, autoshow_enabled)
        return menu

class TrayApp(wx.Frame):

    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, -1, title, size = (1, 1),
            style=wx.FRAME_NO_TASKBAR|wx.NO_FULL_REPAINT_ON_RESIZE)
        
        # ddTaskBarIcon is defined above...
        
        _icon = wx.EmptyIcon()
        _icon.CopyFromBitmap(wx.Bitmap("icon.ico", wx.BITMAP_TYPE_ANY))
        self.trayicon = TrayIcon(_icon, "iShortcut", self) 
        
        self.Hide()
                
        #load the settings
        self.config = ConfigParser.ConfigParser()
        self.config.read("settings.cfg")
        self.NextTrack = util.hotkey(self.config.get("Hotkeys", "NextTrack"))
        self.PrevTrack = util.hotkey(self.config.get("Hotkeys", "PrevTrack"))
        self.PlayPause = util.hotkey(self.config.get("Hotkeys", "PlayPause"))
        self.Stop = util.hotkey(self.config.get("Hotkeys", "Stop"))
        self.ShowInfo = util.hotkey(self.config.get("Hotkeys", "ShowInfo"))
        self.Shuffle = util.hotkey(self.config.get("Hotkeys", "Shuffle"))
        
        self.track = None
        
        #connect to iTunes
        itunes.track_handler = self.autoshow_info
        itunes.exit_handler = self.cleanup
        
        #display current track
        self.popup = None
        self.autoshow_info(forced=True)
        
        #window close event
        wx.EVT_CLOSE(self, self.cleanup)
        
        #bind the playback hotkeys
        self.bind_hotkey(ID_NEXT_TRACK, self.NextTrack)
        self.bind_hotkey(ID_PREV_TRACK, self.PrevTrack)
        self.bind_hotkey(ID_PLAY_PAUSE, self.PlayPause)
        self.bind_hotkey(ID_STOP, self.Stop)
        self.bind_hotkey(ID_SHOW_INFO, self.ShowInfo)
        self.bind_hotkey(ID_SHUFFLE, self.Shuffle)
    
    def autoshow_info(self, track=None, forced=False):
        if autoshow_enabled:
            self.show_info(track, forced)
    
    def show_info(self, track=None, forced=False):
        if forced:
            self.track = track = itunes.com2track(itunes.app.CurrentTrack)
        if self.track != track or forced:
            self.track = track
            if self.popup is None:
                self.popup = InfoPopup(self)
            self.popup.show(self.track)
    
    def bind_hotkey(self, id, key):
        self.RegisterHotKey(
            id,     #a unique ID for this hotkey
            key[1], #the modifier
            key[0]) #the virtual key code
        self.Bind(wx.EVT_HOTKEY, self.on_hotkey, id=id)
    
    def on_hotkey(self, event):
        id = event.GetId()
        if id == ID_NEXT_TRACK:
            itunes.app.NextTrack()
            itunes.app.Play()
            #if event fails, use autoshow so that the user
            #can block it if desired
            if not itunes.event_success:
                self.autoshow_info(forced=True)
        elif id == ID_PREV_TRACK:
            itunes.app.PreviousTrack()
            itunes.app.Play()
            if not itunes.event_success:
                self.autoshow_info(forced=True)
        elif id == ID_PLAY_PAUSE:
            itunes.app.PlayPause()
        elif id == ID_STOP:
            itunes.app.Stop()
        elif id == ID_SHOW_INFO:
            self.show_info(forced=True)
        elif id == ID_SHUFFLE:
            if itunes.app.CanSetShuffle:
                itunes.app.CurrentPlaylist.Shuffle = not itunes.app.CurrentPlaylist.Shuffle
        
    def cleanup(self, evt=None):
        if self.popup is not None:
            self.popup.Show(False)
            self.popup.Destroy()
        self.trayicon.Destroy()
        print "Remaining COM interfaces: " + str(itunes.close())
        wx.GetApp().Exit()

##
# The main application wx.App class
#
class MainApp(wx.App):
    def OnInit(self):
        frame = TrayApp(None, -1, ' ')
        frame.Center(wx.BOTH)
        frame.Show(False)
        return True

def main(argv=None):
    #Connect to itunes
    print "Connecting to iTunes..."
    itunes.connect()

    #Open our system tray application
    print "Opening iShortcut..."
    app = MainApp(0)
    app.MainLoop()

if __name__ == '__main__':
    main()